#include	"match_queue.h"
#include	<string.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<time.h>

static int g_trade_id = 0;
//
MatchQueue::MatchQueue(): _ask_list(0), _bid_list(0)
{
}

//
MatchQueue::~MatchQueue()
{

}


int MatchQueue::InsertOrder(OrderStub* order)
{
    FTDPrice target_price = order->Price;
    PriceNode* p = 0;
    PriceNode* pre = 0;
    PriceNode** p_origin_list = 0; 

    if(BUY == order->BS)
    {
        p_origin_list = &_bid_list;
        p = _bid_list;
        pre = p;
        while(p)
        {
            if(p->price >= target_price)
                break;
            pre = p;
            p = p->next;
        }
    }
    else
    {
        p_origin_list = &_ask_list;
        p = _ask_list;
        pre = p;
        while(p)
        {
            if(p->price <= target_price)
                break;
            pre = p;
            p = p->next;
        }
    }

    if(p == 0 || p->price != target_price) //new price node
    {
        PriceNode* np = _price_node_mem.Alloc();
        np->price = target_price;
        np->next = p;

        np->order_head = 0;
        np->order_tail = 0;

        if(pre != 0 && pre != p)
            pre->next = np;
        else
            *p_origin_list = np;

        p = np;
    }

    OrderNode* op = _order_node_mem.Alloc();
    op->next = 0;
    op->prev = p->order_tail;
    op->order = order;
    if(p->order_tail != 0)
        p->order_tail->next = op;
    p->order_tail = op;
    if(p->order_head == 0)
        p->order_head = op;
    
    return 1;
}
    
int MatchQueue::CancelOrder(OrderStub* order)
{
    FTDPrice target_price = order->Price;
    PriceNode* p = 0;
    PriceNode* pre = 0;

    if(BUY == order->BS)
    {
        p = _bid_list;
        pre = p;
        while(p)
        {
            if(p->price >= target_price)
                break;
            pre = p;
            p = p->next;
        }
    }
    else
    {
        p = _ask_list;
        pre = p;
        while(p)
        {
            if(p->price <= target_price)
                break;
            pre = p;
            p = p->next;
        }
    }

    if(p == 0 || p->price != target_price) //find no price node
    {
        return 0;
    }

    OrderNode* op = p->order_tail; //search from the tail
	while(op)
    {
        if(op->order == order)
        {
            if(op->prev)
                op->prev->next = op->next;
            if(op->next)
                op->next->prev = op->prev;

            if(op == p->order_tail)
                p->order_tail = op->prev;
            if(op == p->order_head)
                p->order_head = op->next;

            _order_node_mem.Free(op);
            return 1;
        }
		op = op->prev;
    }

    return 0;
}
    
void MatchQueue::VirtualMatch(MarketMatchDataChgField* pankou) //match by market data
{
    FTDPrice target_bid_price = pankou->BidPrice;
    FTDPrice target_ask_price = pankou->AskPrice;

    PriceNode* ap = _ask_list;
    while(ap&&ap->price <= target_bid_price)
    {
        OrderNode* op = ap->order_head;
        while(op)
        {
			TradeStub* np = _trade_stub_mem.Alloc();
			np->OrderId = op->order->OrderId;
			np->Price = target_bid_price;
			np->TradeId = g_trade_id++;
			np->Vol = op->order->RemainVol;

			op->order->RemainVol = 0;
			
			 OrderNode* toDel = op;
			op = op->next;
            _order_node_mem.Free(toDel);
        }
        ap->order_head = ap->order_tail = 0;
        ap = ap->next;
    }
    PriceNode* bp = _bid_list;
    while(bp&&bp->price >= target_ask_price)
    {
        OrderNode* op = bp->order_head;
        while(op)
        {
			op->order->RemainVol = 0;

			TradeStub* np = _trade_stub_mem.Alloc();
			np->OrderId = op->order->OrderId;
			np->Price = target_ask_price;
			np->TradeId = g_trade_id++;
			np->Vol = op->order->RemainVol;

            OrderNode* toDel = op;
            op = op->next;

            _order_node_mem.Free(toDel);
        }
        bp->order_head = bp->order_tail = 0;
        bp = bp->next;
    }
}
